

package Statistics;


// Referenced classes of package Statistics:
//            Descriptives, Matrix, OLS

public class LMS
{

    public LMS()
    {
    }

    public Matrix Regress(Matrix x, Matrix y, boolean intercept)
    {
        betas = new Matrix();
        Matrix design = new Matrix(x.n, x.m + 1);
        double bigMedian = 100000000000D;
        Matrix lastBetas = new Matrix();
        int MAXITER = 0;
        int p = x.m;
        this.x = x;
        this.y = y;
        if(intercept)
        {
            int n = x.n;
            int m = x.m;
            for(int i = 0; i < n; i++)
                design.setValue(i, 0, 1.0D);

            for(int i = 0; i < n; i++)
            {
                for(int j = 0; j < m; j++)
                    design.setValue(i, j + 1, x.getValue(i, j));

            }

            this.x = design;
        }
        OLS ols = new OLS();
        Matrix tempx = new Matrix(design.m + 1, design.m);
        Matrix tempy = new Matrix(design.m + 1, 1);
        MAXITER = 500 * design.m + 1;
        for(int iter = 0; iter < MAXITER; iter++)
        {
            int choose[] = getRandomIndex(x.n, design.m + 1);
            for(int i = 0; i < choose.length; i++)
            {
                for(int j = 0; j < design.m; j++)
                {
                    tempx.myData[i][j] = design.myData[choose[i]][j];
                    tempy.myData[i][0] = y.myData[choose[i]][0];
                }

            }

            Matrix tempbetas = ols.Regress(tempx, tempy, false);
            Matrix residuals = y.Diff(x.Mult(tempbetas));
            for(int i = 0; i < residuals.n; i++)
                residuals.myData[i][0] = Math.pow(residuals.myData[i][0], 2D);

            Descriptives d = new Descriptives(residuals);
            double median = d.getMedian();
            if(median < bigMedian)
            {
                lastBetas = tempbetas;
                bigMedian = median;
            }
        }

        return lastBetas;
    }

    public int[] getRandomIndex(int Range, int count)
    {
        int ok = 0;
        int myArr[] = new int[Range];
        int rndArr[] = new int[count];
        for(int i = 0; i < Range; i++)
            myArr[i] = i;

        do
        {
            if(ok == count)
                break;
            int t = (int)(Math.random() * (double)Range);
            if(myArr[t] > -1)
            {
                rndArr[ok] = myArr[t];
                ok++;
                myArr[t] = -1;
            }
        } while(true);
        return rndArr;
    }

    public Matrix betas;
    public Matrix x;
    public Matrix y;
}